﻿using RuoVea.ExIdGen.Contract;
using RuoVea.ExIdGen.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RuoVea.ExIdGen
{
    /// <summary>
    /// 标识Id生成
    /// </summary>
    public class IdGenerator  
    {
        /// <summary>
        /// 
        /// </summary>
        public static IIdGenerator _IdGenInstance;

        /// <summary>
        /// 构造
        /// </summary>
        public IdGenerator() {
            _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = 0 });
        }

        /// <summary>
        /// 机器码
        /// 必须由外部设定，最大值 2^WorkerIdBitLength-1
        /// WorkerId，机器码，最重要参数，无默认值，必须 全局唯一（或相同 DataCenterId 内唯一），必须 程序设定，缺省条件（WorkerIdBitLength取默认值）时最大值63，理论最大值 2^WorkerIdBitLength-1（不同实现语言可能会限定在 65535 或 32767，原理同 WorkerIdBitLength 规则）。不同机器或不同应用实例 不能相同，你可通过应用程序配置该值，也可通过调用外部服务获取值。
        /// * 特别提示：如果一台服务器部署多个独立服务，需要为每个服务指定不同的 WorkerId。
        public IdGenerator(ushort workerId)
        {
            _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = workerId });
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="workerId"></param>
        /// <param name="seqBitLength">序列数位长+机器码位长不超过22 默认值6，取值范围 [3, 21]</param>
        public IdGenerator(ushort workerId,byte seqBitLength)
        {
            _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = 0,SeqBitLength= seqBitLength });
        }

        /// <summary>
        /// 生成新的Id
        /// 调用本方法前，请确保调用了 SetIdGenerator 方法做初始化。
        /// 否则将会初始化一个WorkerId为1的对象。
        /// </summary>
        /// <returns></returns>
        private static long NextId()
        {
            if (_IdGenInstance == null)
            {
                _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = 0 });
            }
            return _IdGenInstance.NewLong();
        }

        #region 自动生成编号
        private static int _sn = 0;
        private static readonly object Locker = new object();
        /// <summary>
        /// 自动生成编号  201008251145409865
        /// </summary>
        /// <returns></returns>
        public static string No()
        {
            lock (Locker)  //lock 关键字可确保当一个线程位于代码的临界区时，另一个线程不会进入该临界区。
            {
                if (_sn == int.MaxValue) _sn = 0; else _sn++;
                Thread.Sleep(10);
                Random random = new Random();
                string strRandom = random.Next(1000, 10000).ToString(); //生成编号
                string code = DateTime.Now.ToString("MMHHmmyyyyssdd") + strRandom;//形如
                return code;
            }
        }
        #endregion

        /// <summary>
        /// 生成 数值型 Id
        /// </summary>
        /// <returns></returns>
        public static long Id
        {
            get
            {
                return NextId();
            }
        }

        public long GetId
        {
            get
            {
                if (_IdGenInstance == null)
                {
                    _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = 0 });
                }
                return _IdGenInstance.NewLong();
            }
        }

        /// <summary>
        /// 生成 字符串 Id
        /// </summary>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string IdStr(string prefix = "")
        {
            return prefix + NextId();
        }
    }
}
